package br.com.simtecnologia.access.controll.role;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import br.com.simtecnologia.access.controll.annotation.ControlledResource;
import br.com.simtecnologia.access.controll.annotation.DeniedLogic;
import br.com.simtecnologia.access.controll.annotation.LoginLogic;

/**
 * Define as regras deacesso a um recurso ou lógica.<br/>
 * <br/>
 * Por exemplo: <br/>
 * <br/>
 * <tt>@{@link ControlledResource}
 * <br/>@{@link Roles}({"funcionario","admin"})
 * <br/>public MeuController {
 * <br/>
 * <br/> &nbsp; &nbsp; //herda apenas as roles do recurso
 * <br/> &nbsp; &nbsp; public void logica1() {...}
 * <br/>
 * <br/> &nbsp; &nbsp; @{@link Roles}(includeResourceRoles=false,value="admin")
 * <br/> &nbsp; &nbsp; public void logica2() {...} //não usa as roles definida no recurso
 * <br/>
 * <br/> &nbsp; &nbsp; @{@link Roles}("cliente") //adiciona cliente a role do recurso
 * <br/> &nbsp; &nbsp; public void logica3() {...}
 * <br/>
 * <br/> &nbsp; &nbsp; @{@link Roles}(denied="funcionario") //negar prevalece sobre liberar
 * <br/> &nbsp; &nbsp; public void logica4() {...}
 * <br/>
 * <br/> &nbsp; &nbsp; @{@link Roles}(includeResourceRoles=false) //gera um warn
 * <br/> &nbsp; &nbsp; public void logica5() {...}
 * <br/>
 * <br/> &nbsp; &nbsp; @{@link DeniedLogic} //todos tem aesso a esta lógica
 * <br/> &nbsp; &nbsp; public void logica6() {...}
 * <br/>
 * <br/> &nbsp; &nbsp; @{@link LoginLogic} //todos tem acesso a esta lógica
 * <br/> &nbsp; &nbsp; public void logica7() {...}
 * <br/>
 * <br/>}</tt>
 * <br/>
 * <br/>
 * Usando a classe {@link RoleResolver} pode-se verificar o acesso as lógicas
 * desse controle, segue algumas analises dos resultandos<br/>
 * <br/>
 * <tt>rolerResolver.hasAccess(logicaX,"admin");</tt> retornará <tt>true</tt> para todas
 * as lógicas exceto a 5.<br/>
 * - Esta lógica 5 irá gerar um WARN no log, pois ela nega as roles do
 * Resource e não define nenhuma nova role, negando acesso a qualquer
 * role.<br/>
 * <br/>
 * <tt>rolerResolver.hasAccess(logicaX,"funcionario");</tt> retornará <tt>true</tt> para todas
 * as lógicas exceto a 2,4 e 5.<br/>
 * - A lógica 2 não inclui as roles do recurso, e não explicita acesso a "funcionário"<br/>
 * - A lógica 4 nega explicitamente o acessa a "funcionario", mesmo no recurso dando acesso, a
 * propriedade denied prevalece sobre a liberação.</br>
 * - O mesmo caso acima essa lógica não da acesso a ninguem e gera um warn.<br/>
 * <br/>
 * <tt>rolerResolver.hasAccess(logicaX,"cliente");</tt> retornará <tt>true</tt> apenas para
 * as lógica 3,6 e 7.<br/>
 * - A lógica 3 porque é a única que libera explicitamente o acesso de "cliente".<br/>
 * - As lógicas 6 e 7 porque a página de login e de aviso de acesso négado devem ser vistas
 * por quem esta logado ou não, e portanto tem acesso por qualquer um.<br/>
 * <br/>
 * <tt>rolerResolver.hasAccess(logicaX,"funcionario","admin");</tt> retornará <tt>true</tt> para todas
 * as lógicas exceto a 4 e 5.<br/>
 * - A lógica 4 nega acesso apenas para funcionário, portanto alguém com as 2 roles, "funcionario" e "admin"
 * mesmo tendo acesso se fosse somente "admin" terá acesso negado com as 2 roles ao mesmo tempo,
 * uma role em denied sempre negará o acesso a lógica, pois prevalecem sobre a liberação do acesso.<br/>
 * <br/>
 * Um usuário deslogado só tem acesso as lógicas 6 e 7, páginas de login e de acesso negado, a tentiva
 * de acessar qualquer uma das outras lógicas levará um redirect para a logica7 solicitando o login.
 * <br/>
 * @author Tomaz Lavieri
 * @see RoleResolver
 */
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE,ElementType.METHOD})
public @interface Roles {
	/**
	 * A lista das roles permitidas a acessar este recurso.
	 */
	String[] value() default {};
	/**
	 * A lista das roles que terão acesso negado a este recurso.
	 */
	String[] denied() default {};
	/**
	 * Caso as definições de Roles do do Contole não devam ser usadas em uma lógica
	 * especifica.<br/>
	 * esse propriedade é ignorada quando a anotação é feita no recurso e não na
	 * lógica.
	 */
	boolean includeResourceRoles() default true;
}
